//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension OAM {
    // MARK: Enums

    public enum ResourceType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case awsApplicationSignalsService = "AWS::ApplicationSignals::Service"
        case awsApplicationSignalsSlo = "AWS::ApplicationSignals::ServiceLevelObjective"
        case awsApplicationinsightsApplication = "AWS::ApplicationInsights::Application"
        case awsCloudwatchMetric = "AWS::CloudWatch::Metric"
        case awsInternetmonitorMonitor = "AWS::InternetMonitor::Monitor"
        case awsLogsLoggroup = "AWS::Logs::LogGroup"
        case awsXrayTrace = "AWS::XRay::Trace"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct ConflictException: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
        }
    }

    public struct CreateLinkInput: AWSEncodableShape {
        /// Specify a friendly human-readable name to use to identify this source account when you are viewing data from it in the monitoring account. You can use a custom label or use the following variables:    $AccountName is the name of the account    $AccountEmail is the globally unique email address of the account    $AccountEmailNoDomain is the email address of the account without the domain name    In the Amazon Web Services GovCloud (US-East) and Amazon Web Services GovCloud (US-West) Regions, the only supported option is to use custom labels, and the $AccountName, $AccountEmail, and $AccountEmailNoDomain variables all resolve as account-id instead of the specified variable.
        public let labelTemplate: String
        /// Use this structure to optionally create filters that specify that only some metric namespaces or log groups are to be shared from the source account to the monitoring account.
        public let linkConfiguration: LinkConfiguration?
        /// An array of strings that define which types of data that the source account shares with the monitoring account.
        public let resourceTypes: [ResourceType]
        /// The ARN of the sink to use to create this link. You can use ListSinks to find the ARNs of sinks. For more information about sinks, see CreateSink.
        public let sinkIdentifier: String
        /// Assigns one or more tags (key-value pairs) to the link.  Tags can help you organize and categorize your resources. You can also use them to scope user permissions by granting a user permission to access or change only resources with certain tag values. For more information about using tags to control access, see Controlling access to Amazon Web Services resources using tags.
        public let tags: [String: String]?

        @inlinable
        public init(labelTemplate: String, linkConfiguration: LinkConfiguration? = nil, resourceTypes: [ResourceType], sinkIdentifier: String, tags: [String: String]? = nil) {
            self.labelTemplate = labelTemplate
            self.linkConfiguration = linkConfiguration
            self.resourceTypes = resourceTypes
            self.sinkIdentifier = sinkIdentifier
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.labelTemplate, name: "labelTemplate", parent: name, max: 64)
            try self.validate(self.labelTemplate, name: "labelTemplate", parent: name, min: 1)
            try self.linkConfiguration?.validate(name: "\(name).linkConfiguration")
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, max: 50)
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, min: 1)
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case labelTemplate = "LabelTemplate"
            case linkConfiguration = "LinkConfiguration"
            case resourceTypes = "ResourceTypes"
            case sinkIdentifier = "SinkIdentifier"
            case tags = "Tags"
        }
    }

    public struct CreateLinkOutput: AWSDecodableShape {
        /// The ARN of the link that is newly created.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that you assigned to this link. If the labelTemplate includes variables, this field displays the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that you specified, with the variables not resolved.
        public let labelTemplate: String?
        /// This structure includes filters that specify which metric namespaces and which log groups are shared from the source account to the monitoring account.
        public let linkConfiguration: LinkConfiguration?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, linkConfiguration: LinkConfiguration? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.linkConfiguration = linkConfiguration
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case linkConfiguration = "LinkConfiguration"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }

    public struct CreateSinkInput: AWSEncodableShape {
        /// A name for the sink.
        public let name: String
        /// Assigns one or more tags (key-value pairs) to the link.  Tags can help you organize and categorize your resources. You can also use them to scope user permissions by granting a user permission to access or change only resources with certain tag values. For more information about using tags to control access, see Controlling access to Amazon Web Services resources using tags.
        public let tags: [String: String]?

        @inlinable
        public init(name: String, tags: [String: String]? = nil) {
            self.name = name
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9_\\.\\-]{1,255}$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct CreateSinkOutput: AWSDecodableShape {
        /// The ARN of the sink that is newly created.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?
        /// The tags assigned to the sink.
        public let tags: [String: String]?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct DeleteLinkInput: AWSEncodableShape {
        /// The ARN of the link to delete.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct DeleteLinkOutput: AWSDecodableShape {
        public init() {}
    }

    public struct DeleteSinkInput: AWSEncodableShape {
        /// The ARN of the sink to delete.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct DeleteSinkOutput: AWSDecodableShape {
        public init() {}
    }

    public struct GetLinkInput: AWSEncodableShape {
        /// The ARN of the link to retrieve information for.
        public let identifier: String
        /// Specifies whether to include the tags associated with the link in the response. When IncludeTags is set to true and the caller has the required permission, oam:ListTagsForResource, the API will return the tags for the specified resource. If the caller doesn't have the required permission, oam:ListTagsForResource, the API will raise an exception. The default value is false.
        public let includeTags: Bool?

        @inlinable
        public init(identifier: String, includeTags: Bool? = nil) {
            self.identifier = identifier
            self.includeTags = includeTags
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
            case includeTags = "IncludeTags"
        }
    }

    public struct GetLinkOutput: AWSDecodableShape {
        /// The ARN of the link.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that you assigned to this link, with the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that was specified when the link was created, with the template variables not resolved.
        public let labelTemplate: String?
        /// This structure includes filters that specify which metric namespaces and which log groups are shared from the source account to the monitoring account.
        public let linkConfiguration: LinkConfiguration?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, linkConfiguration: LinkConfiguration? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.linkConfiguration = linkConfiguration
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case linkConfiguration = "LinkConfiguration"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }

    public struct GetSinkInput: AWSEncodableShape {
        /// The ARN of the sink to retrieve information for.
        public let identifier: String
        /// Specifies whether to include the tags associated with the sink in the response. When IncludeTags is set to true and the caller has the required permission, oam:ListTagsForResource, the API will return the tags for the specified resource. If the caller doesn't have the required permission, oam:ListTagsForResource, the API will raise an exception. The default value is false.
        public let includeTags: Bool?

        @inlinable
        public init(identifier: String, includeTags: Bool? = nil) {
            self.identifier = identifier
            self.includeTags = includeTags
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
            case includeTags = "IncludeTags"
        }
    }

    public struct GetSinkOutput: AWSDecodableShape {
        /// The ARN of the sink.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?
        /// The tags assigned to the sink.
        public let tags: [String: String]?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct GetSinkPolicyInput: AWSEncodableShape {
        /// The ARN of the sink to retrieve the policy of.
        public let sinkIdentifier: String

        @inlinable
        public init(sinkIdentifier: String) {
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct GetSinkPolicyOutput: AWSDecodableShape {
        /// The policy that you specified, in JSON format.
        public let policy: String?
        /// The ARN of the sink.
        public let sinkArn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let sinkId: String?

        @inlinable
        public init(policy: String? = nil, sinkArn: String? = nil, sinkId: String? = nil) {
            self.policy = policy
            self.sinkArn = sinkArn
            self.sinkId = sinkId
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkArn = "SinkArn"
            case sinkId = "SinkId"
        }
    }

    public struct InternalServiceFault: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
        }
    }

    public struct InvalidParameterException: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
        }
    }

    public struct LinkConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Use this structure to filter which log groups are to send log events from the source account to the monitoring account.
        public let logGroupConfiguration: LogGroupConfiguration?
        /// Use this structure to filter which metric namespaces are to be shared from the source account to the monitoring account.
        public let metricConfiguration: MetricConfiguration?

        @inlinable
        public init(logGroupConfiguration: LogGroupConfiguration? = nil, metricConfiguration: MetricConfiguration? = nil) {
            self.logGroupConfiguration = logGroupConfiguration
            self.metricConfiguration = metricConfiguration
        }

        public func validate(name: String) throws {
            try self.logGroupConfiguration?.validate(name: "\(name).logGroupConfiguration")
            try self.metricConfiguration?.validate(name: "\(name).metricConfiguration")
        }

        private enum CodingKeys: String, CodingKey {
            case logGroupConfiguration = "LogGroupConfiguration"
            case metricConfiguration = "MetricConfiguration"
        }
    }

    public struct ListAttachedLinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?
        /// The ARN of the sink that you want to retrieve links for.
        public let sinkIdentifier: String

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil, sinkIdentifier: String) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct ListAttachedLinksItem: AWSDecodableShape {
        /// The label that was assigned to this link at creation, with the variables resolved to their actual values.
        public let label: String?
        /// The ARN of the link.
        public let linkArn: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?

        @inlinable
        public init(label: String? = nil, linkArn: String? = nil, resourceTypes: [String]? = nil) {
            self.label = label
            self.linkArn = linkArn
            self.resourceTypes = resourceTypes
        }

        private enum CodingKeys: String, CodingKey {
            case label = "Label"
            case linkArn = "LinkArn"
            case resourceTypes = "ResourceTypes"
        }
    }

    public struct ListAttachedLinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the attached links.
        public let items: [ListAttachedLinksItem]
        /// The token to use when requesting the next set of links.
        public let nextToken: String?

        @inlinable
        public init(items: [ListAttachedLinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListLinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 5)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListLinksItem: AWSDecodableShape {
        /// The ARN of the link.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that was assigned to this link at creation, with the variables resolved to their actual values.
        public let label: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that this link is attached to.
        public let sinkArn: String?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, label: String? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
        }
    }

    public struct ListLinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the returned links.
        public let items: [ListLinksItem]
        /// The token to use when requesting the next set of links.
        public let nextToken: String?

        @inlinable
        public init(items: [ListLinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListSinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListSinksItem: AWSDecodableShape {
        /// The ARN of the sink.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, name: String? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
        }
    }

    public struct ListSinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the returned sinks.
        public let items: [ListSinksItem]
        /// The token to use when requesting the next set of sinks.
        public let nextToken: String?

        @inlinable
        public init(items: [ListSinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListTagsForResourceInput: AWSEncodableShape {
        /// The ARN of the resource that you want to view tags for. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.  Unlike tagging permissions in other Amazon Web Services services, to retrieve the list of tags for links or sinks you must have the oam:RequestTag permission. The aws:ReguestTag permission does not allow you to tag and untag links and sinks.
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceOutput: AWSDecodableShape {
        /// The list of tags associated with the requested resource.&gt;
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct LogGroupConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Use this field to specify which log groups are to share their log events with the monitoring account. Use the term LogGroupName and one or more of the following operands. Use single quotation marks (') around log group names. The matching of log group names is case sensitive. Each filter has a limit of five conditional operands. Conditional operands are AND and OR.    = and !=     AND     OR     LIKE and NOT LIKE. These can be used only as prefix searches. Include a % at the end of the string that you want to search for and include.    IN and NOT IN, using parentheses ( )    Examples:    LogGroupName IN ('This-Log-Group', 'Other-Log-Group') includes only the log groups with names This-Log-Group and Other-Log-Group.    LogGroupName NOT IN ('Private-Log-Group', 'Private-Log-Group-2') includes all log groups except the log groups with names Private-Log-Group and Private-Log-Group-2.    LogGroupName LIKE 'aws/lambda/%' OR LogGroupName LIKE 'AWSLogs%' includes all log groups that have names that start with aws/lambda/ or AWSLogs.    If you are updating a link that uses filters, you can specify * as the only value for the filter parameter to delete the filter and share all log groups with the monitoring account.
        public let filter: String

        @inlinable
        public init(filter: String) {
            self.filter = filter
        }

        public func validate(name: String) throws {
            try self.validate(self.filter, name: "filter", parent: name, max: 2000)
            try self.validate(self.filter, name: "filter", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case filter = "Filter"
        }
    }

    public struct MetricConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Use this field to specify which metrics are to be shared with the monitoring account. Use the term Namespace and one or more of the following operands. Use single quotation marks (') around namespace names. The matching of namespace names is case sensitive. Each filter has a limit of five conditional operands. Conditional operands are AND and OR.    = and !=     AND     OR     LIKE and NOT LIKE. These can be used only as prefix searches. Include a % at the end of the string that you want to search for and include.    IN and NOT IN, using parentheses ( )    Examples:    Namespace NOT LIKE 'AWS/%' includes only namespaces that don't start with AWS/, such as custom namespaces.    Namespace IN ('AWS/EC2', 'AWS/ELB', 'AWS/S3') includes only the metrics in the EC2, Elastic Load Balancing, and Amazon S3 namespaces.     Namespace = 'AWS/EC2' OR Namespace NOT LIKE 'AWS/%' includes only the EC2 namespace and your custom namespaces.    If you are updating a link that uses filters, you can specify * as the only value for the filter parameter to delete the filter and share all metric namespaces with the monitoring account.
        public let filter: String

        @inlinable
        public init(filter: String) {
            self.filter = filter
        }

        public func validate(name: String) throws {
            try self.validate(self.filter, name: "filter", parent: name, max: 2000)
            try self.validate(self.filter, name: "filter", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case filter = "Filter"
        }
    }

    public struct MissingRequiredParameterException: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
        }
    }

    public struct PutSinkPolicyInput: AWSEncodableShape {
        /// The JSON policy to use. If you are updating an existing policy, the entire existing policy is replaced by what you specify here. The policy must be in JSON string format with quotation marks escaped and no newlines. For examples of different types of policies, see the Examples section on this page.
        public let policy: String
        /// The ARN of the sink to attach this policy to.
        public let sinkIdentifier: String

        @inlinable
        public init(policy: String, sinkIdentifier: String) {
            self.policy = policy
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct PutSinkPolicyOutput: AWSDecodableShape {
        /// The policy that you specified.
        public let policy: String?
        /// The ARN of the sink.
        public let sinkArn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let sinkId: String?

        @inlinable
        public init(policy: String? = nil, sinkArn: String? = nil, sinkId: String? = nil) {
            self.policy = policy
            self.sinkArn = sinkArn
            self.sinkId = sinkId
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkArn = "SinkArn"
            case sinkId = "SinkId"
        }
    }

    public struct ResourceNotFoundException: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
        }
    }

    public struct ServiceQuotaExceededException: AWSErrorShape {
        /// The name of the exception.
        public let amznErrorType: String?
        public let message: String?

        @inlinable
        public init(amznErrorType: String? = nil, message: String? = nil) {
            self.amznErrorType = amznErrorType
            self.message = message
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.amznErrorType = try response.decodeHeaderIfPresent(String.self, key: "x-amzn-ErrorType")
            self.message = try container.decodeIfPresent(String.self, forKey: .message)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
        }
    }

    public struct TagResourceInput: AWSEncodableShape {
        /// The ARN of the resource that you're adding tags to. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.
        public let resourceArn: String
        /// The list of key-value pairs to associate with the resource.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct TagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceInput: AWSEncodableShape {
        /// The ARN of the resource that you're removing tags from. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.
        public let resourceArn: String
        /// The list of tag keys to remove from the resource.
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateLinkInput: AWSEncodableShape {
        /// The ARN of the link that you want to update.
        public let identifier: String
        /// Specifies whether to include the tags associated with the link in the response after the update operation. When IncludeTags is set to true and the caller has the required permission, oam:ListTagsForResource, the API will return the tags for the specified resource. If the caller doesn't have the required permission, oam:ListTagsForResource, the API will raise an exception.  The default value is false.
        public let includeTags: Bool?
        /// Use this structure to filter which metric namespaces and which log groups are to be shared from the source account to the monitoring account.
        public let linkConfiguration: LinkConfiguration?
        /// An array of strings that define which types of data that the source account will send to the monitoring account. Your input here replaces the current set of data types that are shared.
        public let resourceTypes: [ResourceType]

        @inlinable
        public init(identifier: String, includeTags: Bool? = nil, linkConfiguration: LinkConfiguration? = nil, resourceTypes: [ResourceType]) {
            self.identifier = identifier
            self.includeTags = includeTags
            self.linkConfiguration = linkConfiguration
            self.resourceTypes = resourceTypes
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
            try self.linkConfiguration?.validate(name: "\(name).linkConfiguration")
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, max: 50)
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
            case includeTags = "IncludeTags"
            case linkConfiguration = "LinkConfiguration"
            case resourceTypes = "ResourceTypes"
        }
    }

    public struct UpdateLinkOutput: AWSDecodableShape {
        /// The ARN of the link that you have updated.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The label assigned to this link, with the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that was specified when the link was created, with the template variables not resolved.
        public let labelTemplate: String?
        /// This structure includes filters that specify which metric namespaces and which log groups are shared from the source account to the monitoring account.
        public let linkConfiguration: LinkConfiguration?
        /// The resource types now supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        @inlinable
        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, linkConfiguration: LinkConfiguration? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.linkConfiguration = linkConfiguration
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case linkConfiguration = "LinkConfiguration"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }
}

// MARK: - Errors

/// Error enum for OAM
public struct OAMErrorType: AWSErrorType {
    enum Code: String {
        case conflictException = "ConflictException"
        case internalServiceFault = "InternalServiceFault"
        case invalidParameterException = "InvalidParameterException"
        case missingRequiredParameterException = "MissingRequiredParameterException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case tooManyTagsException = "TooManyTagsException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize OAM
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// A resource was in an inconsistent state during an update or a deletion.
    public static var conflictException: Self { .init(.conflictException) }
    /// Unexpected error while processing the request. Retry the request.
    public static var internalServiceFault: Self { .init(.internalServiceFault) }
    /// A parameter is specified incorrectly.
    public static var invalidParameterException: Self { .init(.invalidParameterException) }
    /// A required parameter is missing from the request.
    public static var missingRequiredParameterException: Self { .init(.missingRequiredParameterException) }
    /// The request references a resource that does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The request would cause a service quota to be exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// A resource can have no more than 50 tags.
    public static var tooManyTagsException: Self { .init(.tooManyTagsException) }
    /// The value of a parameter in the request caused an error.
    public static var validationException: Self { .init(.validationException) }
}

extension OAMErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "ConflictException": OAM.ConflictException.self,
        "InternalServiceFault": OAM.InternalServiceFault.self,
        "InvalidParameterException": OAM.InvalidParameterException.self,
        "MissingRequiredParameterException": OAM.MissingRequiredParameterException.self,
        "ResourceNotFoundException": OAM.ResourceNotFoundException.self,
        "ServiceQuotaExceededException": OAM.ServiceQuotaExceededException.self
    ]
}

extension OAMErrorType: Equatable {
    public static func == (lhs: OAMErrorType, rhs: OAMErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension OAMErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
